home *** CD-ROM | disk | FTP | other *** search
-
- /******** rep.c by Dimitri C. Keletsekis *****************************
-
- *** This code compiles into a small executable re-entrant CLI
- *** command for replacing strings in files. It can be compiled
- *** with SAS C 6.50+. The SCOPTIONS file is included. Just do
- *** <sc rep link> to produce it.
- ***
- *** It's may not be the best, it may not be the fastest, but it
- *** works..
- ***
- *** It uses the NOSTARTUP compiler option which means that it
- *** compiles without *any* start-up code from the compiler,
- *** resulting in a smaller, sexier executable.
-
- *************************************************************************/
-
- #define __USE_SYSBASE;
- #include <exec/exec.h>
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <exec/memory.h>
- #include <dos/dosextens.h>
- #include <dos/rdargs.h>
- #include <dos/dostags.h>
-
- #include <string.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <dos.h>
-
- #include <proto/dos.h>
- #include <proto/exec.h>
-
- #define THISPROC ((struct Process *)(SysBase->ThisTask))
- #define Result2(x) THISPROC->pr_Result2 = x
-
- static const char VERSION[] = "\0$VER: Rep 1.4 (D.Keletsekis 2/2/99)";
-
- // prototypes
- LONG rep (void);
- LONG parse (UBYTE *);
-
- LONG rep(void)
- {
- struct ExecBase *SysBase = (*((struct ExecBase **) 4));
- struct DosLibrary *DOSBase=NULL;
- struct RDArgs *rdargs = NULL;
- UBYTE *file, *repstr, *dest;
- UBYTE upstr[256], *str; // string buffer for case insensitive
- LONG rc;
- long args[5];
- struct FileInfoBlock *fib=NULL;
- UBYTE *buff=NULL;
- BPTR fp;
- LONG buffsize, sz;
- int err = 0, c;
- register UBYTE *p, *d, *t, *u;
- UBYTE *endfile=0;
- BOOL INSENSITIVE = 0;
- LONG lstr, lrep; // string lengths
-
- rc = 10; /* return code */
-
- if (!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 36L)))
- { Result2(ERROR_INVALID_RESIDENT_LIBRARY);
- goto endprog;
- }
-
- memset((char *)args, 0, sizeof(args));
- rdargs = ReadArgs("FILE/A,STRING/A,NEWSTRING/A,NEWFILE,I=INSENSITIVE/S", args, NULL);
- if (!rdargs)
- { PrintFault (IoErr(), "REP by dck@hol.gr\nERROR");
- goto endprog;
- }
-
- file = (UBYTE *)args[0];
- str = (UBYTE *)args[1];
- repstr = (UBYTE *)args[2];
- if (args[3]) dest = (UBYTE *)args[3]; else dest = file;
- if (args[4]) INSENSITIVE = 1;
-
- // parse strings for hex, decimals etc
- if (((lstr = parse (str)) == -1) || ((lrep = parse (repstr)) == -1))
- { PutStr ("Error parsing string\n");
- goto endprog;
- }
- // max size of upstr buffer
- if (lstr > 250)
- { PutStr ("String too long\n");
- goto endprog;
- }
-
- /*------------------------------ read file ------------------------*/
-
- if (!(fp = Open (file, MODE_OLDFILE)))
- { PutStr ("Could not open file\n");
- goto endprog;
- }
-
- if (fib = (struct FileInfoBlock *)AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR))
- { if (ExamineFH(fp, fib))
- { buffsize = fib->fib_Size;
- if (buff = (unsigned char *)AllocVec(buffsize + 32, MEMF_CLEAR))
- { sz = Read (fp, buff, buffsize);
- if (sz != buffsize) ++err;
- endfile = &buff[sz];
- }
- }
- FreeVec (fib);
- }
- Close (fp);
-
- if (err)
- { PutStr ("Error reading file\n");
- goto endprog;
- }
- else if (!buff)
- { PutStr ("No memory!\n");
- goto endprog;
- }
-
- // ------------------------- prepare.. -------------------
-
- if (!(fp = Open (dest, MODE_NEWFILE)))
- { PutStr ("Error writing file\n");
- goto endprog;
- }
- p = buff;
-
- // copy to upstr buffer - not with strcpy since there may be NULLs
- for (c=0; c<lstr; ++c) upstr[c] = str[c];
- upstr[c] = 0;
-
- if (INSENSITIVE)
- { d = str;
- u = upstr; // make lower/upper case buffers
- for (c=0; c<lstr; ++c)
- { if ((*d >= 'A') && (*d < 'a')) *d = ((*d) + ('a' - 'A'));
- if ((*u >= 'a') && (*u <= 'z')) *u = ((*u) - ('a' - 'A'));
- ++d; ++u;
- }
- }
-
- // -------------------- DO THE CHACHA ------------------
-
- while (p < endfile)
- {
- if ((*p == *str) || (*p == *upstr))
- { t = p;
- d = str;
- u = upstr;
- for (c = 0; (c < lstr) && ((*d == *t) || (*u == *t)); ++c)
- { ++t; ++d; ++u; }
- if (c == lstr) // found it
- { --t;
- p = t;
- for (c = 0; c < lrep; ++c)
- { if (EOF == (int)(FPutC (fp, repstr[c]))) goto endflag;
- }
- }
- else
- if (EOF == (int)(FPutC (fp, *p))) goto endflag;
- }
- else
- if (EOF == (int)(FPutC (fp, *p))) goto endflag;
-
- ++p;
- }
- rc = 0;
- goto endnoflag; /* i.e. skip error report */
-
- endflag:
- PutStr ("Error writing file\n");
-
- endnoflag:
- Close (fp);
-
- endprog :
- if (rdargs) FreeArgs (rdargs);
- if (buff) FreeVec (buff);
- if (DOSBase) CloseLibrary((struct Library *)DOSBase);
- return (rc);
- }
-
- // --------------------------------------------------------------
- // Parse a string, overwriting it.
- // Return length (may contain NULLs)
- // Return -1 for error
- // --------------------------------------------------------------
-
- LONG parse (UBYTE *str)
- {
- LONG len = 0, c;
- int x;
- UBYTE *p, *s;
- UBYTE hx[5];
-
- if (!str) return (-1);
- if (!str[0]) return (0);
- s = p = str;
-
- while (*p)
- {
- if (*p == '\\') // start of special characters
- { ++p;
- switch (*p)
- { case 'n' : *s = '\n'; ++s; ++p; break;
- case 'r' : *s = '\r'; ++s; ++p; break;
- case 't' : *s = '\t'; ++s; ++p; break;
- case '\"': *s = '\"'; ++s; ++p; break;
- case '\'': *s = '\''; ++s; ++p; break;
- case '\\': *s = '\\'; ++s; ++p; break;
-
- case 'X' :
- case 'x' : // hex
- ++p;
- while (*p && (*p != '\\'))
- { hx[0] = *p; ++p;
- hx[1] = *p; ++p; hx[2] = 0;
- if ((stch_i(hx, &x)) != 2)
- return (-1);
- *s = (UBYTE)x;
- ++s;
- }
- if (*p == '\\') ++p;
- break;
-
- case '#' : // decimal
- ++p;
- c = (*p - '0'); // do first
- ++p;
- while (*p && (*p!='\\') && (*p>='0') && (*p<='9')) // do rest
- { c *= 10;
- c += (LONG)(*p - '0');
- ++p;
- }
- *s = (UBYTE)c;
- ++s;
- if (*p == '\\') ++p;
- break;
-
- default : *s = *p; ++s; ++p; break;
- };
- }
- else
- { *s = *p; ++s; ++p;
- }
- }
- *s = 0; // terminating null
- len = s - str;
- return (len); // return new length
- }
-
-